import * as l from "@/galois/lang";
import { assert } from "chai";

type BlockName = keyof typeof blockDefs & keyof typeof blockIDs;

export const blockDefs = {
  asphalt: l.ToBlock("blocks/asphalt.json"),
  basalt: l.ToBlock("blocks/basalt.json"),
  basalt_brick: l.ToBlock("blocks/basalt_brick.json"),
  basalt_carved: l.ToBlock("blocks/basalt_carved.json"),
  basalt_polished: l.ToBlock("blocks/basalt_polished.json"),
  basalt_shingles: l.ToBlock("blocks/basalt_shingles.json"),
  bedrock: l.ToBlock("blocks/bedrock.json"),
  birch_log: l.ToBlock("blocks/birch_log.json"),
  birch_lumber: l.ToBlock("blocks/birch_lumber.json"),
  birch_reinforced: l.ToBlock("blocks/birch_reinforced.json"),
  birch_stripped: l.ToBlock("blocks/birch_stripped.json"),
  clay: l.ToBlock("blocks/clay.json"),
  clay_brick: l.ToBlock("blocks/clay_brick.json"),
  clay_carved: l.ToBlock("blocks/clay_carved.json"),
  clay_polished: l.ToBlock("blocks/clay_polished.json"),
  clay_shingles: l.ToBlock("blocks/clay_shingles.json"),
  coal_ore: l.ToBlock("blocks/coal_ore.json"),
  cobblestone: l.ToBlock("blocks/cobblestone.json"),
  cobblestone_brick: l.ToBlock("blocks/cobblestone_brick.json"),
  cobblestone_carved: l.ToBlock("blocks/cobblestone_carved.json"),
  cobblestone_polished: l.ToBlock("blocks/cobblestone_polished.json"),
  cobblestone_shingles: l.ToBlock("blocks/cobblestone_shingles.json"),
  copper: l.ToBlock("blocks/copper.json"),
  cotton_fabric: l.ToBlock("blocks/cotton_fabric.json"),
  diamond: l.ToBlock("blocks/diamond.json"),
  diamond_ore: l.ToBlock("blocks/diamond_ore.json"),
  dirt: l.ToBlock("blocks/dirt.json"),
  emberstone: l.ToBlock("blocks/emberstone.json"),
  gold: l.ToBlock("blocks/gold.json"),
  gold_ore: l.ToBlock("blocks/gold_ore.json"),
  granite: l.ToBlock("blocks/granite.json"),
  granite_brick: l.ToBlock("blocks/granite_brick.json"),
  granite_carved: l.ToBlock("blocks/granite_carved.json"),
  granite_polished: l.ToBlock("blocks/granite_polished.json"),
  granite_shingles: l.ToBlock("blocks/granite_shingles.json"),
  grass: l.ToBlock("blocks/grass.json"),
  gravel: l.ToBlock("blocks/gravel.json"),
  hay: l.ToBlock("blocks/hay.json"),
  ice: l.ToBlock("blocks/ice.json"),
  lava: l.ToBlock("blocks/lava.json"),
  led: l.ToBlock("blocks/led.json"),
  limestone: l.ToBlock("blocks/limestone.json"),
  limestone_brick: l.ToBlock("blocks/limestone_brick.json"),
  limestone_carved: l.ToBlock("blocks/limestone_carved.json"),
  limestone_polished: l.ToBlock("blocks/limestone_polished.json"),
  limestone_shingles: l.ToBlock("blocks/limestone_shingles.json"),
  moonstone: l.ToBlock("blocks/moonstone.json"),
  moss: l.ToBlock("blocks/moss.json"),
  muckwad: l.ToBlock("blocks/muckwad.json"),
  mushroom_leather: l.ToBlock("blocks/mushroom_leather.json"),
  neptunium: l.ToBlock("blocks/neptunium.json"),
  neptunium_ore: l.ToBlock("blocks/neptunium_ore.json"),
  oak_log: l.ToBlock("blocks/oak_log.json"),
  oak_lumber: l.ToBlock("blocks/oak_lumber.json"),
  oak_reinforced: l.ToBlock("blocks/oak_reinforced.json"),
  oak_stripped: l.ToBlock("blocks/oak_stripped.json"),
  palm_log: l.ToBlock("blocks/palm_log.json"),
  pumpkin: l.ToBlock("blocks/pumpkin.json"),
  quartzite: l.ToBlock("blocks/quartzite.json"),
  quartzite_brick: l.ToBlock("blocks/quartzite_brick.json"),
  quartzite_carved: l.ToBlock("blocks/quartzite_carved.json"),
  quartzite_polished: l.ToBlock("blocks/quartzite_polished.json"),
  quartzite_shingles: l.ToBlock("blocks/quartzite_shingles.json"),
  rubber_log: l.ToBlock("blocks/rubber_log.json"),
  rubber_lumber: l.ToBlock("blocks/rubber_lumber.json"),
  rubber_reinforced: l.ToBlock("blocks/rubber_reinforced.json"),
  rubber_stripped: l.ToBlock("blocks/rubber_stripped.json"),
  sakura_log: l.ToBlock("blocks/sakura_log.json"),
  sakura_lumber: l.ToBlock("blocks/sakura_lumber.json"),
  sand: l.ToBlock("blocks/sand.json"),
  silver: l.ToBlock("blocks/silver.json"),
  silver_ore: l.ToBlock("blocks/silver_ore.json"),
  snow: l.ToBlock("blocks/snow.json"),
  splintered_muck: l.ToBlock("blocks/splintered_muck.json"),
  stone: l.ToBlock("blocks/stone.json"),
  stone_brick: l.ToBlock("blocks/stone_brick.json"),
  stone_carved: l.ToBlock("blocks/stone_carved.json"),
  stone_polished: l.ToBlock("blocks/stone_polished.json"),
  stone_shingles: l.ToBlock("blocks/stone_shingles.json"),
  sunstone: l.ToBlock("blocks/sunstone.json"),
  template: l.ToBlock("blocks/template.json"),
  soil: l.ToBlock("blocks/soil.json"),
  thatch: l.ToBlock("blocks/thatch.json"),
  wood_crate: l.ToBlock("blocks/wood_crate.json"),
};

export const blockIDs = {
  grass: l.ToBlockID(1),
  dirt: l.ToBlockID(2),
  oak_log: l.ToBlockID(3),
  stone: l.ToBlockID(4),
  cobblestone: l.ToBlockID(5),
  bedrock: l.ToBlockID(6),
  quartzite: l.ToBlockID(7),
  basalt: l.ToBlockID(8),
  limestone: l.ToBlockID(9),
  pumpkin: l.ToBlockID(10),
  gold_ore: l.ToBlockID(11),
  birch_log: l.ToBlockID(12),
  granite: l.ToBlockID(13),
  rubber_log: l.ToBlockID(14),
  basalt_brick: l.ToBlockID(15),
  birch_lumber: l.ToBlockID(16),
  clay: l.ToBlockID(17),
  clay_brick: l.ToBlockID(18),
  coal_ore: l.ToBlockID(19),
  cobblestone_brick: l.ToBlockID(20),
  diamond: l.ToBlockID(21),
  wood_crate: l.ToBlockID(22),
  diamond_ore: l.ToBlockID(23),
  gold: l.ToBlockID(24),
  silver_ore: l.ToBlockID(25),
  granite_brick: l.ToBlockID(26),
  limestone_brick: l.ToBlockID(27),
  neptunium: l.ToBlockID(28),
  stone_brick: l.ToBlockID(29),
  neptunium_ore: l.ToBlockID(30),
  oak_lumber: l.ToBlockID(31),
  quartzite_brick: l.ToBlockID(32),
  silver: l.ToBlockID(33),
  rubber_lumber: l.ToBlockID(34),
  hay: l.ToBlockID(35),
  gravel: l.ToBlockID(36),
  snow: l.ToBlockID(37),
  cotton_fabric: l.ToBlockID(38),
  mushroom_leather: l.ToBlockID(39),
  moss: l.ToBlockID(40),
  basalt_carved: l.ToBlockID(41),
  basalt_polished: l.ToBlockID(42),
  basalt_shingles: l.ToBlockID(43),
  clay_carved: l.ToBlockID(44),
  clay_polished: l.ToBlockID(45),
  clay_shingles: l.ToBlockID(46),
  cobblestone_carved: l.ToBlockID(47),
  cobblestone_polished: l.ToBlockID(48),
  cobblestone_shingles: l.ToBlockID(49),
  granite_carved: l.ToBlockID(50),
  granite_polished: l.ToBlockID(51),
  granite_shingles: l.ToBlockID(52),
  limestone_carved: l.ToBlockID(53),
  limestone_polished: l.ToBlockID(54),
  limestone_shingles: l.ToBlockID(55),
  quartzite_carved: l.ToBlockID(56),
  quartzite_polished: l.ToBlockID(57),
  quartzite_shingles: l.ToBlockID(58),
  stone_carved: l.ToBlockID(59),
  stone_polished: l.ToBlockID(60),
  stone_shingles: l.ToBlockID(61),
  ice: l.ToBlockID(62),
  thatch: l.ToBlockID(63),
  led: l.ToBlockID(64),
  emberstone: l.ToBlockID(65),
  sunstone: l.ToBlockID(66),
  moonstone: l.ToBlockID(67),
  copper: l.ToBlockID(68),
  template: l.ToBlockID(69),
  birch_reinforced: l.ToBlockID(70),
  birch_stripped: l.ToBlockID(71),
  oak_reinforced: l.ToBlockID(72),
  oak_stripped: l.ToBlockID(73),
  rubber_reinforced: l.ToBlockID(74),
  rubber_stripped: l.ToBlockID(75),
  asphalt: l.ToBlockID(76),
  soil: l.ToBlockID(77),
  sakura_log: l.ToBlockID(78),
  lava: l.ToBlockID(79),
  sand: l.ToBlockID(80),
  muckwad: l.ToBlockID(81),
  splintered_muck: l.ToBlockID(82),
  sakura_lumber: l.ToBlockID(83),
  palm_log: l.ToBlockID(84),
};

assert.ok(
  Object.keys(blockIDs).every((key) => blockDefs[key as BlockName]),
  "blockIDs and blockDefs not in sync."
);
assert.ok(
  Object.keys(blockDefs).every((key) => blockIDs[key as BlockName]),
  "blockIDs and blockDefs not in sync."
);

// Assemble the ID to block mappings.
const indexEntries: [l.BlockID, l.Block][] = [];
for (const [name, id] of Object.entries(blockIDs)) {
  indexEntries.push([id, blockDefs[name as BlockName]]);
}

export const colorIDs = {
  blue: 1,
  red: 2,
  green: 3,
  orange: 4,
  white: 5,
  purple: 6,
  pink: 7,
  yellow: 8,
  black: 9,
  tan: 10,
  brown: 11,
  silver: 12,
  cyan: 13,
  magenta: 14,
  brightgreen: 15,
  brightred: 16,
  brightpurple: 17,
  brightpink: 18,
  brightyellow: 19,
  brightblue: 20,
  brightorange: 21,
  lightblue: 22,
} as const;

export const blockIndex = l.ToBlockIndex(
  indexEntries,
  blockIDs.template,
  Object.entries(colorIDs)
);
export const blockAtlas = l.ToAtlas(blockIndex);

const blockMeshes: Record<string, l.BlockItemMesh> = {};
for (const [name, id] of Object.entries(blockIDs)) {
  blockMeshes[`item_meshes/blocks/${name}`] = l.ToItemMesh(id, blockIndex);
}

export function getAssets(): Record<string, l.Asset> {
  return {
    "atlases/blocks": blockAtlas,
    "indices/blocks": blockIndex,
    ...blockMeshes,
    "definitions/primary_colors": l.PrimaryColorTable(Object.entries(colorIDs)),
  };
}
